
local AceConfig = LibStub("AceConfig-3.0")
local AceConfigDialog = LibStub("AceConfigDialog-3.0")
local Sink = LibStub("LibSink-2.0")
local Media = LibStub("LibSharedMedia-3.0")
local db

local addon = LibStub("AceAddon-3.0"):NewAddon("Snarly", "AceConsole-3.0", "AceEvent-3.0")
Snarly = addon

addon.clevents = {}
addon.fails = {}
addon.players = {}
addon.version = "1.0"
addon.options = {
    type = "group",
    name = "Snarly",
    desc = "Configuration",
    handler = addon,
    args = {
        general = {
            type = "group",
            order = 1,
            name = "General Settings",
            desc = "General Settings",
            args = {
                desc1 = {
                    type = "description",
                    name = "Snarly whines to your favourite combat text addon about shit you need to watch out for or remember during certain boss encounters.",
                    order = 1,
                },
                common = {
                    type = "group",
                    order = 2,
                    name = "Common",
                    desc = "Settings shared across all events handled",
                    args = {
                        enabled = {
                            type = "toggle",
                            order = 1,
                            width = "full",
                            name = "Enabled",
                            desc = "Enable or disable the whine",
                            get = function() return db.common.enabled end,
                            set = function(_, n) db.common.enabled = n end,
                        },
                        raidonly = {
                            type = "toggle",
                            order = 2,
                            width = "full",
                            name = "Raid only",
                            desc = "Only whine while in a raid group",
                            get = function() return db.common.raidonly end,
                            set = function(_, n) db.common.raidonly = n end,
                        },
                    },
                },
                announce = {
                    type = "group",
                    order = 3,
                    name = "Announce",
                    desc = "Where and how to announce the whines",
                    args = {
                        sink = Sink.GetSinkAce3OptionsDataTable(addon),
                        color = {
                            type = "color",
                            order = 500,
                            width = "full",
                            name = "Color",
                            --hasalpha = false,
                            get = function(_) local t = db.announce.fontcolor return t.r, t.g, t.b, t.a end,
                            set = function(_, r, g, b, a) local t = db.announce.fontcolor t.r, t.g, t.b, t.a = r, g, b, a end,
                        },
                        fontsize = {
                            type = "range",
                            order = 700,
                            width = "full",
                            name = "Font size",
                            desc = "Set the announcement font size",
                            get = function() return db.announce.fontsize end,
                            set = function(_, n) db.announce.fontsize = n end,
                            min = 10,
                            max = 48,
                            step = 1,
                        },
                        sound = {
                            type = "select",
                            dialogControl = "LSM30_Sound",
                            order = 800,
                            width = "full",
                            name = "Play sound when whining",
                            desc = "Select a sound to play",
                            values = AceGUIWidgetLSMlists.sound,
                            disabled = function() return not db.announce.sound end,
                            get = function() return db.announce.sound end,
                            set = function(_, n) db.announce.sound = n end,
                        },
                    },
                },
                whine = {
                    type = "group",
                    order = 4,
                    name = "Whines",
                    desc = "Whine about this shit",
                    args = {
                        toytrainset = {
                            type = "toggle",
                            order = 2,
                            width = "full",
                            name = "Toy Train Set",
                            desc = "Whine about someone using the toy train set",
                            get = function() return db.whine.toytrainset end,
                            set = function(_, n) db.whine.toytrainset = n end,
                        },
                        voidzone = {
                            type = "toggle",
                            order = 3,
                            width = "full",
                            name = "Void Zone",
                            desc = "Whine when a boss tries to fry you in a void zone",
                            get = function() return db.whine.voidzone end,
                            set = function(_, n) db.whine.voidzone = n end,
                        },
                        iceblock = {
                            type = "toggle",
                            order = 4,
                            width = "full",
                            name = "Ice Block",
                            desc = "Whine about losers being stuck in blocks of ice",
                            get = function() return db.whine.iceblock end,
                            set = function(_, n) db.whine.iceblock = n end,
                        },
                        manabomb = {
                            type = "toggle",
                            order = 5,
                            width = "full",
                            name = "Mana Bomb",
                            desc = "Whine when some idiot tries to blow you up",
                            get = function() return db.whine.manabomb end,
                            set = function(_, n) db.whine.manabomb = n end,
                        },
                        surgeofpower = {
                            type = "toggle",
                            order = 6,
                            width = "full",
                            name = "Surge of Power",
                            desc = "Whine about catching lightning with your face",
                            get = function() return db.whine.surgeofpower end,
                            set = function(_, n) db.whine.surgeofpower = n end,
                        },
                        polarityshift = {
                            type = "toggle",
                            order = 7,
                            width = "full",
                            name = "Polarity Shift",
                            desc = "Whine about having to switch sides",
                            get = function() return db.whine.polarityshift end,
                            set = function(_, n) db.whine.polarityshift = n end,
                        },
                    },
                },
                monitor = {
                    type = "group",
                    order = 5,
                    name = "Monitor",
                    desc = "Lets you monitor specific players for fails",
                    args = {
                        enabled = {
                            type = "toggle",
                            order = 1,
                            width = "full",
                            name = "Enabled",
                            desc = "Enable or disable the monitor",
                            get = function() return db.monitor.enabled end,
                            set = function(_, n) db.monitor.enabled = n end,
                        },
                        players = {
                            type = "multiselect",
                            dialogControl = "Dropdown",
                            order = 2,
                            width = "full",
                            name = "Players",
                            desc = "List of players you can monitor",
                            values = addon.players,
                            get = function(_, a) return addon.players[a] end,
                            set = function(_, a, n) addon.players[a] = n end,
                        },
                        clear = {
                            type = "execute",
                            order = 3,
                            name = "Clear fails",
                            func = function() addon:ClearFails() end,
                        },
                        fails = {
                            type = "toggle",
                            order = 4,
                            width = "full",
                            name = "Monitor fails",
                            desc = "Enable or disable the fail monitor",
                            get = function() return db.monitor.fails end,
                            set = function(_, n) db.monitor.fails = n end,
                        },
                        casts = {
                            type = "toggle",
                            order = 5,
                            width = "full",
                            name = "Monitor casts",
                            desc = "Enable or disable the casting monitor",
                            get = function() return db.monitor.casts end,
                            set = function(_, n) db.monitor.casts = n end,
                        },
                    },
                },
            },
        },
    },
}

AceConfig:RegisterOptionsTable("Snarly", addon.options)

Media:Register("sound", "Mono Warning 1", "Interface\\AddOns\\Snarly\\Media\\warn1.wav")
Media:Register("sound", "Mono Warning 2", "Interface\\AddOns\\Snarly\\Media\\warn2.wav")
Media:Register("sound", "Mono Warning 3", "Interface\\AddOns\\Snarly\\Media\\warn3.wav")
Media:Register("sound", "Mono Warning 4", "Interface\\AddOns\\Snarly\\Media\\warn4.wav")
Media:Register("sound", "Mono Warning 5", "Interface\\AddOns\\Snarly\\Media\\warn5.wav")
Media:Register("sound", "Loud and annoying", "Sound\\Spells\\PVPFlagTaken.wav")

function addon:Whine(text)
    if db.raidonly and not UnitInRaid("player") then return end
    if Sink then
        local t = db.announce.fontcolor
        Sink.Pour(addon, text, t.r, t.g, t.b, nil, nil, nil, nil, nil, nil)
    end
    if db.sound then
        PlaySoundFile(Media:Fetch("sound", db.announce.sound))
    end
end

function addon:UpdatePlayerList()
    if not UnitInRaid("player") then return end
    for i = 1, GetNumRaidMembers() do
        local name = GetRaidRosterInfo(i)
        self.players[name] = false
    end
end

function addon:ClearFails()
    self.fails = {}
end

function addon:OpenConfig(input)
    if input == "config" or not InterfaceOptionsFrame:IsResizable() then
        InterfaceOptionsFrame:Hide()
        AceConfigDialog:SetDefaultSize("Snarly", 650, 500)
        AceConfigDialog:Open("Snarly")
    else
        InterfaceOptionsFrame_OpenToCategory(self.optionsFrames.Snarly)
    end
end

function addon:OnProfileChanged(event, database, newprofilekey)
    db = database.profile
end

function addon:SetupOptions()
    self.optionsFrames = {}
    LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Snarly", self.options)
    self.optionsFrames.Snarly = AceConfigDialog:AddToBlizOptions("Snarly", nil, nil, "general")
    self:RegisterModuleOptions("Profiles", LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db), "Profiles")
    self.options.args.Profiles.order = -2
    self:RegisterChatCommand("snarly", "OpenConfig")
end

function addon:RegisterModuleOptions(name, optiontable, displayname)
    self.options.args[name] = (type(optiontable) == "function") and optiontable() or optiontable
    self.optionsFrames[name] = AceConfigDialog:AddToBlizOptions("Snarly", displayname, "Snarly", name)
end

function addon:OnProfileChanged(event, database, newProfileKey)
    db = database.profile
end

function addon:OnInitialize()
    self.db = LibStub("AceDB-3.0"):New("SnarlyDB", defaults, "Default")
    self.db.RegisterCallback(self, "OnProfileChanged", "OnProfileChanged")
    self.db.RegisterCallback(self, "OnProfileCopied", "OnProfileChanged")
    self.db.RegisterCallback(self, "OnProfileReset", "OnProfileChanged")
    self.db:RegisterDefaults(self:GetDefaultConfig())
    db = self.db.profile

    Sink.SetSinkStorage(addon, db.announce.sink)

    self:SetupOptions()
    
    self.OnInitialize = nil
end

function addon:OnEnable()
    self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
    self:RegisterEvent("RAID_ROSTER_UPDATE")
    self:RegisterEvent("PARTY_MEMBERS_CHANGED")
    self:RegisterEvent("CHAT_MSG_RAID_BOSS_EMOTE")
    self:RegisterEvent("UNIT_DIED")
end

function addon:OnDisable()
    self:UnRegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
    self:UnRegisterEvent("RAID_ROSTER_UPDATE")
    self:UnRegisterEvent("PARTY_MEMBERS_CHANGED")
    self:UnRegisterEvent("CHAT_MSG_RAID_BOSS_EMOTE")
    self:UnRegisterEvent("UNIT_DIED")
end

function addon:GetDefaultConfig()
    local default = {
        profile = {
            common = {
                enabled = true,
                raidonly = true,
            },
            announce = {
                sound = "Flag Challenged!",
                fontcolor = { r = 1, g = 0.1, b = 0.1, a = 1},
                fontsize = 32,
                sink = {},
            },
            whine = {
                toytrainset = true,
                voidzone = true,
                iceblock = true,
                manabomb = true,
                surgeofpower = true,
                polarityshift = true,
            },
            monitor = {
                enabled = true,
                fails = true,
                casts = true,
            },
        },
    }
    return default
end

function addon:COMBAT_LOG_EVENT_UNFILTERED(e, timestamp, event, ...)
    local handler = self.clevents[event]
    if handler then
        handler(self, timestamp, event, ...)
    end
end

function addon.clevents:SPELL_CAST_START(timestamp, event, srcguid, srcname, srcflags, dstguid, dstname, dstflags, spellid, spellname, spellschool)
    if spellid == 61031 and db.whine.toytrainset then
        self:Whine(srcname:upper().." SET US UP THE TRAIN!")
    elseif spellid == 28089 and srcname == "Thaddius" and db.whine.polarityshift then
        self:Whine("POLARITY SHIFT INCOMING")
    end
    if db.monitor.enabled and db.monitor.casts then
        for name, monitor in pairs(self.players) do
            if srcname == name and monitor == true then
                self:Print(srcname.." casts "..spellname)
            end
        end
    end
end

local voidzone = { 27810, 59127, 57579 }
function addon.clevents:SPELL_CAST_SUCCESS(timestamp, event, srcguid, srcname, srcflags, dstguid, dstname, dstflags, spellid, spellname, spellschool)
    if db.whine.voidzone then
        for _, checkid in pairs(voidzone) do
            if checkid == spellid then
                self:Whine("CHECK YOUR FEET!", true)
            end
        end
    end
end

function addon.clevents:SPELL_AURA_APPLIED(timestamp, event, srcguid, srcname, srcflags, dstguid, dstname, dstflags, spellid, spellname, spellschool, auratype)
    if spellid == 27808 and db.whine.iceblock then
        self:Whine(dstname:upper().." NEEDS HEALING!", true)
    elseif spellid == 27819 and db.whine.manabomb then
        if dstname == UnitName("player") then
            self:Whine("YOU GOT THE BOMB!", true)
        else
            self:Whine(dstname:upper().." HAS THE BOMB!", true)
        end
    elseif spellid == 60936 and dstname == UnitName("player") and db.whine.surgeofpower then
        self:Whine("SURGE OF POWER ON YOU!", true)
    end
end

function addon.clevents:SPELL_DAMAGE(timestamp, event, srcguid, srcname, srcflags, dstguid, dstname, dstflags, spellid, spellname, spellschool)
    if not db.monitor.enabled or not db.monitor.fails then return end
    for name, monitor in pairs(self.players) do
        if dstname == name and monitor == true then
            if bit.band(dstflags, COMBATLOG_OBJECT_TYPE_PLAYER) > 0 then
                if spellname == "Flame Tsunami" then
                    self:Print(name.." fails at lava waves")
            	end
                if spellname == "Eruption" then
                    self:Print(name.." fails at dancing")
                end
                if spellname == "Void Blast" then
                    self:Print(name.." fails at void zones")
                end
                if spellname == "Frost Breath" then
                    self:Print(name.." fails at finding an ice block")
                end
                if spellname == "Explode" then
                    self:Print(name.." fails at frogger")
                end
                if spellname == "Deep Breath" then
                    self:Print(name.." fails at finding an anti-magic zone")
                end
            end
        end
    end
end

function addon:UNIT_DIED()
end

function addon:CHAT_MSG_RAID_BOSS_EMOTE()
end

function addon:RAID_ROSTER_UPDATE()
    self:UpdatePlayerList()
end

function addon:PARTY_MEMBERS_CHANGED()
    self:UpdatePlayerList()
end
